home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Magnum One
/
Magnum One (Mid-American Digital) (Disc Manufacturing).iso
/
d20
/
bsrc_250.arc
/
XMREC.C
< prev
next >
Wrap
C/C++ Source or Header
|
1991-09-16
|
37KB
|
1,249 lines
/*--------------------------------------------------------------------------*/
/* */
/* */
/* ------------ Bit-Bucket Software, Co. */
/* \ 10001101 / Writers and Distributors of */
/* \ 011110 / Freely Available<tm> Software. */
/* \ 1011 / */
/* ------ */
/* */
/* (C) Copyright 1987-91, Bit Bucket Software Co., a Delaware Corporation. */
/* */
/* */
/* This module was written by Bob Hartman */
/* */
/* */
/* BinkleyTerm Xmodem Receiver State Machine */
/* */
/* */
/* For complete details of the licensing restrictions, please refer */
/* to the License agreement, which is published in its entirety in */
/* the MAKEFILE and BT.C, and also contained in the file LICENSE.250. */
/* */
/* USE OF THIS FILE IS SUBJECT TO THE RESTRICTIONS CONTAINED IN THE */
/* BINKLEYTERM LICENSING AGREEMENT. IF YOU DO NOT FIND THE TEXT OF */
/* THIS AGREEMENT IN ANY OF THE AFOREMENTIONED FILES, OR IF YOU DO */
/* NOT HAVE THESE FILES, YOU SHOULD IMMEDIATELY CONTACT BIT BUCKET */
/* SOFTWARE CO. AT ONE OF THE ADDRESSES LISTED BELOW. IN NO EVENT */
/* SHOULD YOU PROCEED TO USE THIS FILE WITHOUT HAVING ACCEPTED THE */
/* TERMS OF THE BINKLEYTERM LICENSING AGREEMENT, OR SUCH OTHER */
/* AGREEMENT AS YOU ARE ABLE TO REACH WITH BIT BUCKET SOFTWARE, CO. */
/* */
/* */
/* You can contact Bit Bucket Software Co. at any one of the following */
/* addresses: */
/* */
/* Bit Bucket Software Co. FidoNet 1:104/501, 1:343/491 */
/* P.O. Box 460398 AlterNet 7:491/0 */
/* Aurora, CO 80046 BBS-Net 86:2030/1 */
/* Internet f491.n343.z1.fidonet.org */
/* */
/* Please feel free to contact us at any time to share your comments about */
/* our software and/or licensing policies. */
/* */
/*--------------------------------------------------------------------------*/
/* Include this file before any other includes or defines! */
#include "includes.h"
void Find_Char (int);
int Header_in_data (unsigned char *);
void Send_ACK (XMARGSP);
void Send_NAK (XMARGSP);
long Open_Xmodem_File (XMARGSP);
int XRInit (XMARGSP, int);
int XREnd (XMARGSP, int);
int XRRecInit (XMARGSP);
int XRBrecInit (XMARGSP);
int XRRecStart (XMARGSP);
int XRWaitFirst (XMARGSP);
int XRWaitBlock (XMARGSP);
int XRRestart (XMARGSP);
int XRSetOvrdr (XMARGSP);
STATES Xmodem_Receiver[] = {
{ "XRInit", XRInit },
{ "XREnd", XREnd },
{ "XR0", XRRecInit },
{ "XR0B", XRBrecInit },
{ "XR1", XRRecStart },
{ "XR2", XRWaitFirst },
{ "XR3", XRWaitBlock },
{ "XR4", XRRestart },
{ "XR5", XRSetOvrdr }
};
long Open_Xmodem_File (XMARGSP args)
{
char *s1, *s2;
if (args->file_pointer == NULL)
{
args->temp_name = calloc (1, 80);
if (args->path != NULL)
(void) strcpy (args->temp_name, args->path);
s1 = &(args->temp_name[strlen (args->temp_name)]);
(void) strcpy (s1, "BTXXXXXX");
s2 = mktemp (args->temp_name);
if ((s2 == NULL) || ((args->file_pointer = fopen (s2, "wb")) == NULL))
{
status_line (MSG_TXT(M_TEMP_NOT_OPEN), s2);
return (-1L);
}
}
throughput (0, 0L);
return (0L);
}
long Set_Up_Restart (XMARGSP args)
{
char foo[100];
char foo1[50];
struct stat st;
args->sub_results = 0;
/* Look for file in directory */
if (args->path != NULL)
(void) strcpy (foo, args->path);
if ((args->received_name != NULL) &&
(strlen (args->received_name) > 0) &&
args->options.Resync)
{
(void) strcat (foo, args->received_name);
if (stat (foo, &st) == 0)
{
if ((st.st_size == args->filelen) && (st.st_atime == (time_t)(args->save_filetime.oneword.timedate)))
{
if ((args->file_pointer = fopen (foo, "rb+")) != NULL)
{
throughput (0, 0L);
(void) fseek (args->file_pointer, 0L, SEEK_END);
args->sub_results = DID_RESYNC;
args->temp_name = calloc (1, 80);
(void) strcpy (args->temp_name, foo);
args->prev_bytes = args->filelen;
status_line (MSG_TXT(M_ALREADY_HAVE), foo);
status_line (MSG_TXT(M_SYNCHRONIZING_EOF));
return (args->total_blocks + 1L);
}
}
}
/* Look for file in .Z file */
if (dexists (Abortlog_name))
{
(void) sprintf (Resume_info, "%ld %lo", args->filelen, args->save_filetime.oneword.timedate);
if (check_failed (Abortlog_name, args->received_name, Resume_info, foo1))
{
foo[0] = '\0';
/* Here it looks like it was a failed WaZOO session */
if (args->path != NULL)
(void) strcpy (foo, args->path);
(void) strcat (foo, foo1);
if ((args->file_pointer = fopen (foo, "rb+")) != NULL)
{
(void) stat (foo, &st);
throughput (0, 0L);
args->temp_name = calloc(1, 80);
(void) strcpy (args->temp_name, foo);
args->prev_bytes = (st.st_size / 128L) * 128L;
(void) fseek (args->file_pointer, args->prev_bytes, SEEK_SET);
status_line (MSG_TXT(M_SYNCHRONIZING_OFFSET), args->prev_bytes);
return (args->prev_bytes / 128L + 1L);
}
}
}
}
return (Open_Xmodem_File (args));
}
void Finish_Xmodem_Receive (XMARGSP args)
{
struct stat st;
char new_name[80];
struct utimbuf times;
int i, j, k;
/* Set the file's time and date stamp */
if ((args->save_header == SOH) || (args->save_header == SYN))
{
(void) fclose (args->file_pointer);
times.modtime = times.UT_ACTIME = (time_t) args->save_filetime.oneword.timedate;
(void) utime (args->temp_name, (UTIMBUF *)×);
}
else
{
(void) strcpy (args->received_name, "");
(void) fclose (args->file_pointer);
}
if (args->result == SUCCESS)
{
/* Get the file information */
(void) stat (args->temp_name, &st);
throughput (1, (unsigned long) (st.st_size - args->prev_bytes));
update_files (0);
if (args->sub_results & DID_RESYNC)
{
status_line ("%s: %s", MSG_TXT(M_FILE_RECEIVED), args->temp_name);
}
else
{
new_name[0] = '\0';
if (args->path != NULL)
(void) strcpy (new_name, args->path);
if ((args->filename == NULL) || (strlen (args->filename) == 0))
{
if (strlen (args->received_name) > 0)
(void) strcat (new_name, args->received_name);
else
(void) strcat (new_name, "BAD_FILE.000");
}
else
{
(void) strcat (new_name, args->filename);
}
i = (int) strlen (args->temp_name) - 1;
j = (int) strlen (new_name) - 1;
if (args->temp_name[i] == '.')
args->temp_name[i] = '\0';
if (new_name[j] == '.')
{
new_name[j] = '\0';
--j;
}
i = 0;
k = is_arcmail (new_name, j);
status_line ("%s: %s", MSG_TXT(M_FILE_RECEIVED), new_name);
if ((!overwrite) || k)
{
while (rename (args->temp_name, new_name))
{
if (isdigit (new_name[j]))
new_name[j]++;
else new_name[j] = '0';
if (!isdigit (new_name[j]))
{
return;
}
i = 1;
}
CLEAR_IOERR ();
}
else
{
(void) unlink (new_name);
while (rename (args->temp_name, new_name))
{
if (!i)
{
status_line (MSG_TXT(M_ORIGINAL_NAME_BAD), new_name);
}
if (isdigit (new_name[j]))
new_name[j]++;
else new_name[j] = '0';
if (!isdigit (new_name[j]))
{
return;
}
i = 1;
}
CLEAR_IOERR ();
}
if (i)
{
if (locate_y && !(fullscreen && un_attended))
gotoxy (2, locate_y - 1);
status_line (MSG_TXT(M_RENAME_MSG), new_name);
}
}
remove_abort (Abortlog_name, args->received_name);
}
else
{
if ((args->received_name != NULL) && (strlen (args->received_name) > 0) && (args->save_header != 0))
{
(void) sprintf (Resume_info, "%ld %lo", args->filelen, args->save_filetime.oneword.timedate);
add_abort (Abortlog_name, args->received_name, args->temp_name, args->path, Resume_info);
}
else
{
/* File aborted, so remove all traces of it */
if (args->temp_name != NULL)
(void) unlink (args->temp_name);
}
}
if (args->temp_name != NULL) {
free (args->temp_name);
}
}
void Get_Telink_Info (XMARGSP args)
{
char *p1;
char junkbuff[100];
TLDATAP t;
unsigned int i, j;
struct tm tmstruc;
time_t curr_time;
/* Figure out how many blocks we will get */
t = (TLDATAP) &(args->header);
args->total_blocks = (t->filelength + 127)/ 128;
t->nullbyte = '\0';
p1 = strchr (t->filename, ' ');
if (p1 != NULL)
*p1 = '\0';
(void) strcpy (args->received_name, t->filename);
args->save_header = args->header;
if (args->save_header == SYN)
{
i = t->filetime.twowords.time;
j = t->filetime.twowords.date;
curr_time = time (NULL);
tmstruc = *localtime (&curr_time); /* Structure assignment */
tmstruc.tm_year = (j >> 9) + 70;
tmstruc.tm_mon = (j >> 5) & 0x0f;
tmstruc.tm_mday = j & 0x1f;
tmstruc.tm_hour = i >> 11;
tmstruc.tm_min = (i >> 5) & 0x3f;
tmstruc.tm_sec = i & 0x1f;
args->save_filetime.oneword.timedate = mktime (&tmstruc);
}
else
{
args->save_filetime.oneword.timedate = t->filetime.oneword.timedate;
}
args->filelen = t->filelength;
(void) sprintf (junkbuff, MSG_TXT(M_RECEIVE_MSG),
args->total_blocks, t->filename, t->sendingprog, t->filelength);
(void) strncpy (args->sending_program, t->sendingprog, 15);
if (un_attended && fullscreen)
{
clear_filetransfer ();
sb_move (file_hWnd, 1, 2);
FlLnModeSet (FILE_LN_2, 1);
sb_puts( GetDlgItem (file_hWnd, FILE_LN_1), junkbuff );
elapse_time ();
sb_show ();
}
else
{
status_line ("+%s", junkbuff);
(void) printf ("\n");
locate_y = wherey ();
locate_x = wherex ();
}
}
int Read_Block (XMARGSP args)
{
unsigned char *p; /* Pointers to XMODEM data */
int i; /* Counter */
int j; /* Counter start */
unsigned char c; /* character being processed */
int in_char;
char junkbuff[128];
long head_timer;
struct _pkthdr *packet; /* FTS-0001 packet type */
struct _pkthdr45 *pkt0045; /* FSC-0045 packet type */
struct _pkthdr39 *pkt0039; /* FSC-0039 packet type */
unsigned int cwtest; /* Used to verify FSC-0039 type */
if (got_ESC ())
{
status_line (MSG_TXT(M_KBD_MSG));
return (KBD_ERR);
}
/* Set up to point into the XMODEM data structure */
p = (unsigned char *) &(args->header);
/* Get the first character that is waiting */
*p = (unsigned char) TIMED_READ (8);
head_timer = timerset (6000);
j = 1;
while (!timeup (head_timer))
{
/* Now key off of the header character */
switch (*p)
{
case EOT: /* End of file */
/* Is this a valid EOT */
if (args->total_blocks <= args->WriteBLK)
{
return (EOT_BLOCK);
}
else
{
status_line (MSG_TXT(M_UNEXPECTED_EOF), args->total_blocks);
return (BAD_BLOCK);
}
case SYN: /* Telink block */
/* For Telink, read all of the data except the checksum */
for (i = 1; i < sizeof (TLDATA) - 2; i++)
{
/* If we go more than 5 second, then we have a short block */
if ((in_char = TIMED_READ (5)) < 0)
{
return (BAD_BLOCK);
}
*(++p) = (unsigned char) (in_char & 0xff);
}
/* if the block number or its complement are wrong, return error */
if ((args->block_num != 0) || (args->block_num_comp != 0xff))
{
return (BAD_BLOCK);
}
/* Now calculate the checksum - Telink block always checksum mode */
Data_Check ((XMDATAP) &(args->header), CHECKSUM);
/* See if we can receive the checksum byte */
if ((in_char = TIMED_READ (10)) < 0)
{
Xmodem_Error (MSG_TXT(M_TIMEOUT), 0L);
return (BAD_BLOCK);
}
/* Was it right */
c = (unsigned char) (in_char & 0xff);
if (c != args->data_check[0])
{
Xmodem_Error (MSG_TXT(M_CHECKSUM), 0L);
return (BAD_BLOCK);
}
/* Everything looks good, it must be a legal TELINK block */
Get_Telink_Info (args);
return (TELINK_BLOCK);
case SOH: /* Normal data block */
args->datalen = 128;
/* Read in all of the data for an XMODEM block except the checksum */
p += (j - 1);
for (i = j; i < sizeof (XMDATA) - 2; i++)
{
/* If we go more than 5 seconds, then it is a short block */
if ((in_char = TIMED_READ (5)) < 0)
{
return (BAD_BLOCK);
}
*(++p) = (unsigned char) (in_char & 0xff);
}
/* The block number is 0 to 255 inclusive */
c = (unsigned char) (args->blocknum & 0xff);
/* Properly calculate the CRC or checksum */
Data_Check ((XMDATAP) &(args->header), args->options.do_CRC ? CRC : CHECKSUM);
/* Can we get the checksum byte */
if ((in_char = TIMED_READ (10)) < 0)
{
Xmodem_Error (MSG_TXT(M_TIMEOUT), args->WriteBLK);
return (BAD_BLOCK);
}
/* Is it the right value */
c = (unsigned char) (in_char & 0xff);
if (c != args->data_check[0])
{
status_line (">Xmodem Receive: Bad %s", (args->options.do_CRC)?"CRC":"checksum");
Xmodem_Error (MSG_TXT(M_CRC_MSG), args->WriteBLK);
if (args->options.do_CRC)
(void) TIMED_READ (5);
return (BAD_BLOCK);
}
/* If we are in CRC mode, do the second byte */
if (args->options.do_CRC)
{
/* Can we get the character */
if ((in_char = TIMED_READ (10)) < 0)
{
status_line (">Xmodem Receive: Timeout waiting for CRC byte 2");
Xmodem_Error (MSG_TXT(M_TIMEOUT), args->WriteBLK);
return (BAD_BLOCK);
}
/* Is it right */
c = (unsigned char) (in_char & 0xff);
if (c != args->data_check[1])
{
Xmodem_Error (MSG_TXT(M_CRC_MSG), args->WriteBLK);
return (BAD_BLOCK);
}
}
/* Do we have a valid data block */
if (args->block_num_comp != (unsigned char)((~(args->block_num)) & 0xff))
{
if (!(args->options.SEAlink))
{
Xmodem_Error (MSG_TXT(M_JUNK_BLOCK), args->WriteBLK);
return (BAD_BLOCK);
}
p = (unsigned char *) &(args->header);
j = Header_in_data (p);
if (j)
{
continue;
}
j = 1;
Find_Char (SOH);
*p = (unsigned char) TIMED_READ (0);
}
if ((args->WriteBLK == 1) && (args->header == SOH) && (args->block_num == 0))
{
Get_Telink_Info (args);
return (SEALINK_BLOCK);
}
if (first_block)
{
packet = (struct _pkthdr *) args->data;
pkt0045 = (struct _pkthdr45 *) packet;
pkt0039 = (struct _pkthdr39 *) packet;
if (!remote_capabilities)
{
remote_addr.Net = packet->orig_net;
remote_addr.Node = packet->orig_node;
if (packet->rate == 2)
{
/* This is a FSC-0045 (type 2.2) packet! */
remote_addr.Zone = packet->orig_zone;
remote_addr.Point = (unsigned) pkt0045->orig_point;
strncpy (junkbuff, (char *)(pkt0045->orig_domain), 8);
junkbuff[8] = '\0';
remote_addr.Domain = find_domain (junkbuff);
}
else
{
remote_addr.Domain = NULL;
cwtest = (((pkt0039->CapValid) & 0x7f00) >> 8) +
(((pkt0039->CapValid) & 0x007f) << 8);
if (cwtest == (unsigned int)((pkt0039->CapWord) & 0x7f7f))
{
/* This is a FSC-0039 packet! */
remote_addr.Zone = pkt0039->orig_zone;
remote_addr.Point = pkt0039->orig_point;
}
else
{
remote_addr.Zone = packet->orig_zone;
remote_addr.Point = 0;
}
}
/*
* Here we have extracted the Zone, Net, Node, Point and Domain from the
* packet -- regardless of type. Now see if we need to map to a fake net
* or to mung the address because it's someone else's point.
*/
if ((remote_addr.Point > 0) &&
(pvtnet >= 0) &&
((remote_addr.Zone == alias[assumed].Zone) || (remote_addr.Zone == 0)) &&
(remote_addr.Net == boss_addr.Net) &&
(remote_addr.Node == boss_addr.Node))
{
remote_addr.Net = pvtnet;
remote_addr.Node = remote_addr.Point;
remote_addr.Point = 0;
}
else if ((pvtnet >= 0) && (remote_addr.Point > 0))
{
remote_addr.Point = 0;
remote_addr.Node = -1;
}
}
if (who_is_he)
{
if (!remote_addr.Zone && !remote_addr.Net && !remote_addr.Node)
{
LOWER_DTR (); /* Bad trip, cut it off */
timer (2); /* Wait two secs */
return(CARRIER_ERR); /* Get out of here! */
}
if (nodefind (&remote_addr, 1))
{
if (!remote_addr.Zone)
remote_addr.Zone = found_zone;
(void) sprintf (junkbuff, "%s: %s (%s)",
MSG_TXT(M_REMOTE_SYSTEM),
newnodedes.SystemName,
Full_Addr_Str (&remote_addr));
}
else
{
(void) sprintf (junkbuff, "%s: %s (%s)",
MSG_TXT(M_REMOTE_SYSTEM),
MSG_TXT(M_UNKNOWN_MAILER),
Full_Addr_Str (&remote_addr));
}
last_type (2, &remote_addr);
status_line (junkbuff);
}
if (args->sending_program[0] != '\0')
{
status_line ("%s %s", MSG_TXT(M_REMOTE_USES), args->sending_program);
}
else
{
log_product (packet->product, 0, packet->serial);
}
who_is_he = 0;
first_block = 0;
}
if (args->WriteBLK == args->total_blocks)
{
args->datalen = (int) (args->filelen - ((args->WriteBLK - 1) * 128));
}
/* If we got this far, it is a valid data block */
args->recblock = args->block_num;
return (XMODEM_BLOCK);
default: /* Bad block */
if ((args->blocknum <= 1) || (PEEKBYTE () < 0))
return (BAD_BLOCK);
/* Garbage header, return bad */
*p = (unsigned char) TIMED_READ (0);
}
}
return (BAD_BLOCK);
}
int XRInit (XMARGSP args, int start_state)
{
char *HoldName;
args->tries = 0;
args->goodfile = 1;
XON_DISABLE ();
HoldName = HoldAreaNameMunge(&called_addr);
(void) sprintf (Abortlog_name, "%s%s.Z\0",
HoldName, Hex_Addr_Str (&remote_addr));
args->sending_program[0] = '\0';
return (start_state);
}
int XREnd (XMARGSP args, int cur_state)
{
args->result = cur_state;
Finish_Xmodem_Receive (args);
return (cur_state);
}
int XRRecInit (XMARGSP args)
{
args->options.SEAlink = 0;
args->options.SLO = 0;
args->options.Resync = 0;
args->options.MacFlow = 0;
args->options.do_CRC = 1;
args->blocknum = 0;
args->WriteBLK = 1;
args->curr_byte = 0L;
args->tries = 0;
return (XR1);
}
int XRBrecInit (XMARGSP args)
{
args->options.SEAlink = 0;
args->options.SLO = 0;
args->options.Resync = 0;
args->options.MacFlow = 0;
args->options.do_CRC = 1;
args->blocknum = 0;
args->WriteBLK = 1;
args->curr_byte = 0L;
args->tries = 0;
return (XR2);
}
int XRRecStart (XMARGSP args)
{
Send_NAK (args);
return (XR2);
}
int XRWaitFirst (XMARGSP args)
{
long XR2Timer;
XR2Timer = timerset (800);
if (args->tries >= 10)
{
args->goodfile = 0;
return (TIME_ERR);
}
if (args->tries == 5)
{
args->options.do_CRC = 0;
++(args->tries);
return (XR1);
}
while (CARRIER)
{
switch (Read_Block (args))
{
case EOT_BLOCK:
args->WriteBLK = 0;
Send_ACK (args);
return (SUCCESS_EOT);
case TELINK_BLOCK:
if (Open_Xmodem_File (args) == -1L)
return (OPEN_ERR);
Send_ACK (args);
args->tries = 0;
return (XR3);
case SEALINK_BLOCK:
args->options.SEAlink = no_sealink ? 0 : 1;
if (args->options.SEAlink && !no_resync)
args->options.Resync = (((SEADATAP) (&(args->header)))->Resync) != 0;
return (XR4);
case XMODEM_BLOCK:
if (args->recblock == 1)
{
if (Open_Xmodem_File (args) == -1L)
return (OPEN_ERR);
(void) fwrite (args->data, sizeof (unsigned char), args->datalen, args->file_pointer);
++(args->WriteBLK);
args->curr_byte = 128L;
++(args->blocknum);
Send_ACK (args);
args->tries = 0;
return (XR3);
}
/* Fallthrough on wrong block */
case BAD_BLOCK:
++(args->tries);
return (XR1);
case CARRIER_ERR:
case KBD_ERR:
return (CARRIER_ERR);
}
if (timeup (XR2Timer))
{
++(args->tries);
return (XR1);
}
}
return (CARRIER_ERR);
}
int XRWaitBlock (XMARGSP args)
{
int blocknum_copy;
if (args->tries >= 10)
{
args->goodfile = 0;
return (TIME_ERR);
}
while (CARRIER)
{
switch (Read_Block (args))
{
case EOT_BLOCK:
args->options.SLO = 0;
Send_ACK (args);
return (SUCCESS);
case XMODEM_BLOCK:
blocknum_copy = (int)args->blocknum & 0xff;
if (args->recblock == ((blocknum_copy - 1) & 0xff))
{
--(args->blocknum);
Send_ACK (args);
return (XR3);
}
if (args->recblock == blocknum_copy)
{
(void) fwrite (args->data, sizeof (unsigned char), args->datalen, args->file_pointer);
++(args->WriteBLK);
args->curr_byte += 128L;
Send_ACK (args);
args->tries = 0;
return (XR3);
}
if (args->recblock < blocknum_copy)
{
args->recblock += 256;
}
if ((args->recblock > blocknum_copy) && (args->recblock <= ((blocknum_copy + 127) & 0xff)))
{
if (args->tries != 0)
{
/* We have sent at least one nak, now only send them
every so often to allow buffers to drain */
if ((args->recblock - blocknum_copy) % 16)
return (XR3);
/* If it is a multiple of 16, then check that it is
higher than 32 */
if ((args->recblock - blocknum_copy) / 16 < 2)
return (XR3);
}
}
/* fallthrough on bad block */
case BAD_BLOCK:
Send_NAK (args);
++(args->tries);
return (XR3);
case CARRIER_ERR:
case KBD_ERR:
return (CARRIER_ERR);
}
}
return (CARRIER_ERR);
}
int XRRestart (XMARGSP args)
{
long c;
c = Set_Up_Restart (args);
if (c == -1L)
return (OPEN_ERR);
if ((!c) || (!(args->options.Resync)))
{
Send_ACK (args);
args->tries = 0;
}
else
{
args->WriteBLK = c;
args->curr_byte = (c - 1) * 128L;
args->blocknum = (unsigned char) ((args->WriteBLK) & 0xff);
Send_NAK (args);
}
return (XR5);
}
int XRSetOvrdr (XMARGSP args)
{
if (!no_overdrive)
args->options.SLO = (((SEADATAP) (&(args->header)))->SLO) != 0;
if (args->options.SLO)
show_block ((long) (args->WriteBLK - 1), " *Overdrive*", args);
return (XR3);
}
int Xmodem_Receive_File (char *path, char *filename)
{
XMARGS xmfile;
int res;
locate_y = wherey ();
locate_x = wherex ();
(void) memset (&xmfile, 0, sizeof (XMARGS));
xmfile.path = path;
xmfile.filename = filename;
xmfile.total_blocks = -1L;
xmfile.sent_ACK = 0;
res = state_machine (Xmodem_Receiver, &xmfile, XR0);
return (res);
}
int Batch_Xmodem_Receive_File (char *path, char *filename)
{
XMARGS xmfile;
int res;
locate_y = wherey ();
locate_x = wherex ();
(void) memset (&xmfile, 0, sizeof (XMARGS));
xmfile.path = path;
xmfile.filename = filename;
xmfile.total_blocks = -1L;
xmfile.sent_ACK = 0;
res = state_machine (Xmodem_Receiver, &xmfile, XR0B);
return (res);
}
int SAInit (XMARGSP, int);
int SAEnd (XMARGSP, int);
int SAClearLine (XMARGSP);
int SASendACK (XMARGSP);
int SASEAlink (XMARGSP);
int SAIncBlk (XMARGSP);
STATES ACK_States[] = {
{ "SAInit", SAInit },
{ "SAEnd", SAEnd },
{ "SA0", SAClearLine },
{ "SA1", SASendACK },
{ "SA2", SASEAlink },
{ "SA3", SAIncBlk }
};
int SAInit (XMARGSP args, int start_state)
{
happy_compiler = args->tries; /* Makes the compiler happy! */
return (start_state);
}
int SAEnd (XMARGSP args, int cur_state)
{
happy_compiler = args->tries; /* Makes the compiler happy! */
return (cur_state);
}
int SAClearLine (XMARGSP args)
{
long SA0Timer;
SA0Timer = timerset (3000);
if (args->options.SLO)
return (SA3);
if (args->options.SEAlink)
return (SA1);
while (CARRIER && !timeup (SA0Timer))
{
if (PEEKBYTE () >= 0)
{
(void) TIMED_READ (0);
time_release ();
continue;
}
return (SA1);
}
return (TIME_ERR);
}
int SASendACK (XMARGSP args)
{
SENDBYTE (ACK);
args->sent_ACK = 1;
return (SA2);
}
int SASEAlink (XMARGSP args)
{
if (!(args->options.SEAlink))
return (SA3);
SENDBYTE (args->blocknum);
SENDBYTE ((unsigned char)~(args->blocknum));
return (SA3);
}
void show_block (long b, char *c, XMARGSP args)
{
char j[100];
int i;
long k;
if (fullscreen && un_attended)
{
elapse_time();
sb_move (file_hWnd, 2, 2);
sb_puts( GetDlgItem (file_hWnd, FILE_LN_2 + GD_STATUS),
ultoa (((unsigned long) b), e_input, 10));
if (c)
sb_puts( GetDlgItem (file_hWnd, FILE_LN_2 + GD_STATUS), c );
k = args->filelen - args->curr_byte;
if (k < 0L)
k = 0L;
i = (int) ((k * 10 / cur_baud.rate_value * 100 /
((args->save_header == SOH) ? 94 : 70) + 59) / 60);
(void) sprintf (j, "%3d min", i);
sb_move (file_hWnd, 2, 69);
sb_puts( GetDlgItem (file_hWnd, FILE_LN_2 + GD_STATUS), j );
sb_show ();
}
else
{
gotoxy (locate_x, locate_y);
(void) printf ("%s", ultoa (((unsigned long) b), e_input, 10));
if (c)
(void) printf ("%s", c);
}
}
int SAIncBlk (XMARGSP args)
{
++(args->blocknum);
if ((args->options.SLO) &&
(((args->WriteBLK > 0) && (!((args->WriteBLK - 1) & 0x001F)) && (args->WriteBLK < args->total_blocks)) ||
(args->WriteBLK >= args->total_blocks)))
{
show_block ((long) (args->WriteBLK - 1), " *Overdrive*", args);
}
else if ((!(args->options.SLO)) && (args->WriteBLK > 0))
{
show_block ((long) (args->WriteBLK - 1), NULL, args);
}
return (SUCCESS);
}
void Send_ACK (XMARGSP args)
{
(void) state_machine (ACK_States, args, SA0);
}
void Send_Resync_Packet (XMARGSP);
int SNInit (XMARGSP, int);
int SNEnd (XMARGSP, int);
int SNClearLine (XMARGSP);
int SNSendNAK (XMARGSP);
int SNSEAlink (XMARGSP);
int SNAckResync (XMARGSP);
STATES NAK_States[] = {
{ "SNInit", SNInit },
{ "SNEnd", SNEnd },
{ "SN0", SNClearLine },
{ "SN1", SNSendNAK },
{ "SN2", SNSEAlink },
{ "SN3", SNAckResync }
};
int SNInit (XMARGSP args, int start_state)
{
happy_compiler = args->tries; /* Makes the compiler happy! */
return (start_state);
}
int SNEnd (XMARGSP args, int cur_state)
{
happy_compiler = args->tries; /* Makes the compiler happy! */
return (cur_state);
}
int SNClearLine (XMARGSP args)
{
long SN0Timer;
SN0Timer = timerset (3000);
if (args->options.Resync)
{
Send_Resync_Packet (args);
return (SN3);
}
if (args->options.SEAlink)
return (SN1);
while (CARRIER && !timeup (SN0Timer))
{
if (PEEKBYTE () >= 0)
{
(void) TIMED_READ (0);
time_release ();
continue;
}
return (SN1);
}
return (TIME_ERR);
}
int SNSendNAK (XMARGSP args)
{
if (args->options.do_CRC && (args->sent_ACK == 0))
SENDBYTE (WANTCRC);
else
SENDBYTE (NAK);
return (SN2);
}
int SNSEAlink (XMARGSP args)
{
if (!(args->options.SEAlink))
return (SUCCESS);
SENDBYTE (args->blocknum);
SENDBYTE ((unsigned char)~(args->blocknum));
return (SUCCESS);
}
int SNAckResync (XMARGSP args)
{
long SN3Timer;
int c;
SN3Timer = timerset (3000);
while (CARRIER && !timeup (SN3Timer))
{
if ((unsigned int)(c = TIMED_READ (10)) == 0xffff)
{
Send_Resync_Packet (args);
continue;
}
if (c == ACK)
{
big_pause (1);
c = PEEKBYTE();
if ((c == SOH) || (c == EOT))
return (SUCCESS);
}
}
if (!CARRIER)
return (CARRIER_ERR);
else
return (TIME_ERR);
}
void Send_NAK (XMARGSP args)
{
(void) state_machine (NAK_States, args, SN0);
}
void Send_Resync_Packet (XMARGSP args)
{
unsigned char resyncit[30];
unsigned int nak_crc;
SENDBYTE (SYN);
(void) sprintf ((char *) resyncit, "%ld", args->WriteBLK);
SENDCHARS ((char *) resyncit, strlen ((char *) resyncit), 1);
nak_crc = crc_block ((unsigned char *) resyncit, (int) strlen ((char *) resyncit));
SENDBYTE (ETX);
SENDBYTE ((unsigned char) (nak_crc & 0xff));
CLEAR_INBOUND ();
SENDBYTE ((unsigned char) (nak_crc >> 8));
}
void Xmodem_Error (char *s, long block_number)
{
char j[50];
char k[50];
(void) sprintf (j, "%s %s %ld", s, MSG_TXT(M_ON_BLOCK), block_number);
(void) sprintf (k, "%-49.49s", j);
status_line (">Xmodem Error: %s", k);
if (fullscreen && un_attended)
{
sb_move (file_hWnd, 2, 20);
sb_puts( GetDlgItem (file_hWnd, FILE_LN_2 + GD_SIZE), k );
sb_show ();
}
else
{
gotoxy (locate_x + 20, locate_y);
(void) cputs (k);
}
}
void Find_Char (int c)
{
long t1;
long t2;
t1 = timerset (3000);
t2 = timerset (100);
while (!timeup (t1) && !timeup (t2))
{
if (!CARRIER)
break;
if (PEEKBYTE () == (c & 0xff))
break;
else if (PEEKBYTE () >= 0)
{
(void) TIMED_READ (0);
t2 = timerset (100);
}
}
}
int Header_in_data (unsigned char *p)
{
int i;
int j;
char *p1;
p1 = (char *) p;
++p1;
j = sizeof (XMDATA) - 2;
for (i = 1; i < j; i++, p1++)
{
if (*p1 == SOH)
{
(void) memcpy (p, p1, (unsigned int) (j - i));
return (j - i);
}
}
return (0);
}